package org.sea.mybator.util;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Reflection {
    public static Object getProperty(Object obj, String fieldname) throws Exception {
        Object result = null;
        Class<? extends Object> objClass = obj.getClass();
        Field field = objClass.getField(fieldname);
        result = field.get(obj);
        return result;
    }

    public static Object getStaticProperty(String className, String fieldName) throws Exception {
        Class<? extends Object> cls = Class.forName(className);
        Field field = cls.getField(fieldName);
        Object provalue = field.get(cls);
        return provalue;
    }

    public static Object getPrivatePropertyValue(Object obj, String propertyName) throws Exception {
        Class<? extends Object> cls = obj.getClass();
        Field field = cls.getDeclaredField(propertyName);
        field.setAccessible(true);
        Object retvalue = field.get(obj);
        return retvalue;
    }

    public static Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
        if (args == null) {
            args = new Object[0];
        }
        Class<? extends Object> cls = owner.getClass();
        @SuppressWarnings("unchecked")
        Class<? extends Object>[] argclass = new Class[args.length];
        int i = 0;
        for (int j = argclass.length; i < j; i++) {
            argclass[i] = args[i].getClass();
        }
        Method method = cls.getMethod(methodName, argclass);
        return method.invoke(owner, args);
    }
    public static Object invokePrivateMethod(Object owner, String methodName, Object[] args) throws Exception {
        if (args == null) {
            args = new Object[0];
        }
        Class<? extends Object> cls = owner.getClass();
        @SuppressWarnings("unchecked")
        Class<? extends Object>[] argclass = new Class[args.length];
        int i = 0;
        for (int j = argclass.length; i < j; i++) {
            argclass[i] = args[i].getClass();
        }
        Method method = cls.getDeclaredMethod(methodName, argclass);
        method.setAccessible(true);
        return method.invoke(owner, args);
    }

    public static Object invokeStaticMethod(String className, String methodName, Object[] args) throws Exception {
        if (args == null) {
            args = new Object[0];
        }
        Class<? extends Object> cls = Class.forName(className);
        @SuppressWarnings("unchecked")
        Class<? extends Object> [] argclass = new Class[args.length];
        int i = 0;
        for (int j = argclass.length; i < j; i++) {
            argclass[i] = args[i].getClass();
        }
        Method method = cls.getMethod(methodName, argclass);
        return method.invoke(null, args);
    }

    @SuppressWarnings("rawtypes")
    public static Object newInstance(String className, Object[] args) throws Exception {
        Class<?> clss = Class.forName(className);
        if (args == null) {
            args = new Object[0];
        }
        Class[] argclass = new Class[args.length];
        int i = 0;
        for (int j = argclass.length; i < j; i++) {
            argclass[i] = args[i].getClass();
        }
        Constructor cons = clss.getConstructor(argclass);
        return cons.newInstance(args);
    }
    @SuppressWarnings("rawtypes")
    public static boolean isInstance(Object obj, Class cls) {
        return cls.isInstance(obj);
    }
    @SuppressWarnings("rawtypes")
    public static List<Object> getFiledValue(Object obj, List<String> fieldNameList) throws Exception {
        if ((fieldNameList == null) || (fieldNameList.size() == 0)) {
            return null;
        }
        Class classType = obj.getClass();
        List<Object> result = new ArrayList<Object>();
        for (String filedName : fieldNameList) {
            Field field = null;
            Object value = null;
            try {
                field = classType.getDeclaredField(filedName);
            } catch (NoSuchFieldException e) {
                System.err.println(classType + " NoSuchFieldException(" + filedName + ")");
            }
            if (field == null) {
                value = "";
            } else {
                field.setAccessible(true);
                value = field.get(obj);
            }
            result.add(value);
        }
        return result;
    }

    public static Object copyProperty(Object ori, Object des) throws Exception {
        if ((ori == null) || (des == null)) {
            return ori;
        }
        Field[] desFields = des.getClass().getDeclaredFields();
        Field[] oriFields = ori.getClass().getDeclaredFields();
        for (Field desField : desFields) {
            for (Field oriField : oriFields) {
                if (desField.getName().equals(oriField.getName())) {
                    desField.setAccessible(true);
                    desField.set(des, oriField.get(ori));
                }
            }
        }
        return des;
    }

    public static Object getByArray(Object array, int index) {
        return Array.get(array, index);
    }

    public static List<String> reg(String contents) {
        List<String> keysList = new ArrayList<String>();
        Pattern pattern = Pattern.compile("\\$\\{[\\w]+\\}");
        Matcher matcher = pattern.matcher(contents);
        while (matcher.find()) {
            String key = matcher.group();
            key = key.substring(1, key.length() - 1).trim();
            System.out.println(key);
            keysList.add(key);
        }

        return keysList;
    }

    public static String getKeyFromExpresion(String contents, String pre, String after) {
        if (contents == null) {
            return "";
        }
        pre = pre == null ? "" : pre;
        after = after == null ? "" : after;
        return contents.substring(pre.length(), contents.length() - after.length());
    }

    public static void main(String[] args) throws Exception {
        Util.regularMatcher("\\$\\{[\\w]+\\}", "${89a}123${1A}o");
    }
}
